package performance;

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 在循环中使用filter的用例场景
 *
 * @author long
 */
public class FilterUseCase {

    /**
     * 业务背景：导出数据，首先从数据库查询基础数据，然后根据productCode到其他模块查看数据，补全其他信息
     * 1：如果遍历orderList，每个order都要到productList里面找一遍，在最坏的情况下，时间复杂度是O(n)
     * 2：而Map.get() 时间复杂度 没有发生hash碰撞 最好情况为O(1) , 最坏单向链表为O(n)
     */
    @Test
    public void test1(){
        // 订单量
        int size = 50000;

        // 模拟从数据库查询订单数据
        List<Order> orderList = getOrderFromDb(size);

        // 模拟从其他系统查询产品信息
        List<Integer> codeList = orderList.stream().map(Order::getProductCode).distinct().collect(Collectors.toList());
        List<Product> productList = getProductFromRpc(codeList);

        final Map<Integer,Product> productMap = productList.stream().collect(Collectors.toMap(Product::getProductCode, Function.identity(),(x, y)->x));

        long start = System.currentTimeMillis();
        // 补全产品名称信息
        for(Order order:orderList){
//            Product product = productList.stream()
//                    .filter(p-> Objects.equals(p.getProductCode(),order.getProductCode()))
//                    .findFirst().orElse(null);
            Product product = productMap.get(order.getProductCode());
            if(product != null){
                order.setProductName(product.getProductName());
            }
        }
        System.out.println("耗时："+(System.currentTimeMillis()-start)+" ms");

    }

    private List<Order> getOrderFromDb(int size){
        List<Order> resultList = new ArrayList<>();
        for(int i = 0;i<size;i++){
            Order order = new Order();
            order.setProductCode(i);
            resultList.add(order);
        }
        return resultList;
    }

    private List<Product> getProductFromRpc(List<Integer> codeList){
        List<Product> resultList = new ArrayList<>();
        for(int i = 0;i<codeList.size();i++){
            Product product = new Product();
            product.setProductCode(codeList.get(i));
            product.setProductName("name"+i);
            resultList.add(product);
        }
        return resultList;
    }

}
